//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using OpenLS.Core.Serialization;

namespace OpenLS.Chart
{
    public class Bar3DChart : BarChartBase, I3DChart
    {
        private Axis _firstAxis;
        private int _gapDepth = 150;
        private int _gapWidth = 150;
        private Axis _secondAxis;
        private ChartShape _shape;
        private Axis _thirdAxis;

        public Bar3DChart()
        {
            FirstAxis = new CategoryAxis();
            FirstAxis.Position = AxisPosition.Bottom;
            SecondAxis = new ValueAxis();
            SecondAxis.Position = AxisPosition.Left;
            ThirdAxis = new SeriesAxis();
            FirstAxis.CrossAxis = SecondAxis;
            SecondAxis.CrossAxis = FirstAxis;
            ThirdAxis.CrossAxis = SecondAxis;
        }
        internal override void OnDirectionChanged(BarDirection direction)
        {
            Axis valueAxis = ValueAxis;
            Axis categoryAxis = CategoryAxis;
            if (direction == BarDirection.Bar)
            {
                switch (valueAxis.Position)
                {
                    case AxisPosition.Left:
                    case AxisPosition.Right:
                        valueAxis.Position = AxisPosition.Bottom;
                        break;
                }
                switch (categoryAxis.Position)
                {
                    case AxisPosition.Bottom:
                    case AxisPosition.Top:
                        categoryAxis.Position = AxisPosition.Left;
                        break;
                }
            }

        }
        public ValueAxis ValueAxis
        {
            get
            {
                return GetFirstAxis<ValueAxis>();
            }
        }

        private T GetFirstAxis<T>() where T: Axis
        {
            foreach (Axis axis in GetAxes())
                if (axis is T)
                    return (T) axis;
            return null;
        }

        public CategoryAxis CategoryAxis
        {
            get
            {
                return GetFirstAxis<CategoryAxis>();
            }
        }
        public SeriesAxis SeriesAxis
        {
            get
            {
                return GetFirstAxis<SeriesAxis>();
            }
        }


        public Axis FirstAxis
        {
            get { return _firstAxis; }
            set
            {
                ReplaceCrossAxis(_firstAxis, value);
                _firstAxis = value; notifyPropertyChanged("FirstAxis");
            }
        }

        public Axis SecondAxis
        {
            get { return _secondAxis; }
            set
            {
                ReplaceCrossAxis(_secondAxis, value);
                _secondAxis = value; notifyPropertyChanged("SecondAxis");
            }
        }

        public Axis ThirdAxis
        {
            get { return _thirdAxis; }
            set
            {
                ReplaceCrossAxis(_thirdAxis, value);
                _thirdAxis = value; notifyPropertyChanged("ThirdAxis");
            }
        }


        public int GapWidth
        {
            get { return _gapWidth; }
            set { _gapWidth = value; notifyPropertyChanged("GapWidth");}
        }

        public int GapDepth
        {
            get { return _gapDepth; }
            set { _gapDepth = value; notifyPropertyChanged("GapDepth");}
        }

        public ChartShape Shape
        {
            get { return _shape; }
            set { _shape = value; notifyPropertyChanged("Shape");}
        }

        protected override void VerifyAxes()
        {
            Debug.WriteLine("todo: verify axes for " + GetType());
        }
        

        internal override void ReadXmlCore(ReadContext context)
        {
            using (var c = context.Read("bar3DChart"))
            {
                ReadXmlBase(c); //\\
                GapWidth = c.ReadOptionalElementIntegerAttribute("gapWidth", 150);
                GapDepth = c.ReadOptionalElementIntegerAttribute("gapDepth", 150);
                Shape =
                    c.ReadOptionalElementEnumAttribute("shape", "val", ChartShape.Box,
                                                                       ChartShape.Box);
                AxisResolver r = ReadContextData.GetAxisResolver(c);
                r.AddAction(c.ReadElementUIntegerAttribute("axId"), delegate(Axis a) { FirstAxis = a; });
                r.AddAction(c.ReadElementUIntegerAttribute("axId"), delegate(Axis a) { SecondAxis = a; });
                r.AddAction(c.ReadOptionalElementUIntegerAttribute("axId"), delegate(Axis a) { ThirdAxis = a; });
                c.WarnIf("crtExt");
            }
        }

        internal override void WriteXmlCore(WriteContext context)
        {
            using (WriteContext c = context.Write("bar3DChart"))
            {
                WriteXmlBase(c); //\\
                c.WriteOptionalElementIntegerAttribute("gapWidth", GapWidth, 150);
                c.WriteOptionalElementIntegerAttribute("gapDepth", GapDepth, 150);
                c.WriteOptionalElementEnumAttribute("shape", "val", Shape, ChartShape.Box,
                                                                    ChartShape.Box);
                c.WriteElementUIntegerAttribute("axId", "val", FirstAxis.Id);
                c.WriteElementUIntegerAttribute("axId", "val", SecondAxis.Id);
                if (ThirdAxis != null)
                    c.WriteElementUIntegerAttribute("axId", "val", _thirdAxis.Id);
                c.WarnIf("crtExt");
            }
        }


        internal override IEnumerable<Axis> GetAxes()
        {
            yield return FirstAxis;
            yield return SecondAxis;
            yield return ThirdAxis;
        }
    }
}